//
// Created by Max on 2025/5/28.
//
#include <dlfcn.h>
#include "../MicLoader.h"
#include "MicConfig.h"

MicConfig::MicConfig() : mHandle(0) {
    LOGD("constructed");
}

MicConfig::~MicConfig() {
    LOGD("destructed");
}

int MicConfig::Init(int channelNum, int sampleRate) {
    mHandle = 0;
    if (InitFunc() != MI_SUCCESS) {
        LOGE("Find Mtk Function Failed!");
        return MI_FAILURE;
    }

    if (InitMic() != MI_SUCCESS) {
        LOGE("Init Mtk Mic Failed!");
        return MI_FAILURE;
    }

    if (OpenMic(channelNum, sampleRate) != MI_OK) {
        LOGE("Open Mtk Mic Failed!");
        return MI_FAILURE;
    }

    return MI_SUCCESS;
}

int MicConfig::DeInit() {
    if (CloseMic() != MI_OK) {
        LOGE("CloseMic Error");
        return MI_FAILURE;
    }

    if (DeInitMic() != MI_SUCCESS) {
        LOGE("DeInitMic Error");
        return MI_FAILURE;
    }
    return MI_SUCCESS;
}

int MicConfig::getMicPeriodSize() {
    MI_S32 period_size = 0;
    MI_RESULT u32ErrCode = MI_OK;
    MI_VOC_AttrType_e eArrtType = E_MI_VOC_ATTR_TYPE_PERIOD_SIZE;
    MI_VOC_GetAttrParams_t stVocGetAttrParams;

    u32ErrCode = g_pFunc_voc_get_attr(mHandle, eArrtType, &stVocGetAttrParams,
                                      (void *) &period_size);
    if (u32ErrCode != MI_OK) {
        LOGE("Error voc_get_period_size: %d", u32ErrCode);
        return MI_ERR_FAILED;
    }
    return period_size;
}

int MicConfig::getMicPeriodCount() {
    MI_S32 period_count = 0;
    MI_RESULT u32ErrCode = MI_OK;
    MI_VOC_AttrType_e eArrtType = E_MI_VOC_ATTR_TYPE_PERIOD_COUNT;
    MI_VOC_GetAttrParams_t stVocGetAttrParams;

    u32ErrCode = g_pFunc_voc_get_attr(mHandle, eArrtType, &stVocGetAttrParams,
                                      (void *) &period_count);
    if (u32ErrCode != MI_OK) {
        LOGE("Error haier_vol_control_get_mic_period_count: %d", u32ErrCode);
        return MI_ERR_FAILED;
    }
    return period_count;
}

int MicConfig::InitFunc() {
    pLibraryHandle = dlopen("libmtkvoc.so", RTLD_LAZY);
    if (!pLibraryHandle) {
        LOGE("pcm load v=libmtkvoc.so failed, %s", dlerror());
        return MI_FAILURE;
    }
    LOGD("pcm dl open  libmtkvoc.so success!");
    g_pFunc_voc_init = (pFUNC_VOC_INIT) dlsym(pLibraryHandle, "a_mtktvapi_voc_MI_VOC_Init");
    if (!g_pFunc_voc_init) {
        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }
    g_pFunc_voc_open = (pFUNC_VOC_OPEN) dlsym(pLibraryHandle, "a_mtktvapi_voc_MI_VOC_Open");
    if (!g_pFunc_voc_open) {
        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }

    g_pFunc_voc_close = (pFUNC_VOC_CLOSE) dlsym(pLibraryHandle, "a_mtktvapi_voc_MI_VOC_Close");
    if (!g_pFunc_voc_close) {
        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }

    g_pFunc_voc_read = (pFUNC_VOC_READ) dlsym(pLibraryHandle, "a_mtktvapi_voc_MI_VOC_Read");
    if (!g_pFunc_voc_read) {

        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }

    g_pFunc_voc_set_attr = (pFUNC_VOC_SET_ATTR) dlsym(pLibraryHandle,
                                                      "a_mtktvapi_voc_MI_VOC_SetAttr");
    if (!g_pFunc_voc_set_attr) {
        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }

    g_pFunc_voc_get_attr = (pFUNC_VOC_GET_ATTR) dlsym(pLibraryHandle,
                                                      "a_mtktvapi_voc_MI_VOC_GetAttr");
    if (!g_pFunc_voc_get_attr) {
        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }

    g_pFunc_voc_get_handle = (pFUNC_VOC_GET_HANDLE) dlsym(pLibraryHandle,
                                                          "a_mtktvapi_voc_MI_VOC_GetHandle");
    if (!g_pFunc_voc_get_handle) {

        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }

    g_pFunc_voc_deinit = (pFUNC_VOC_DEINIT) dlsym(pLibraryHandle, "a_mtktvapi_voc_MI_VOC_DeInit");
    if (!g_pFunc_voc_deinit) {

        LOGE("%s", dlerror());
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }
    return MI_SUCCESS;
}

int MicConfig::InitMic() {
    MI_RESULT eErrCode = MI_OK;
    MI_VOC_InitParams_t stInitParams;

    memset(&stInitParams, 0, sizeof(MI_VOC_InitParams_t));
    eErrCode = g_pFunc_voc_init(&stInitParams);
    if (eErrCode != MI_OK && eErrCode != MI_HAS_INITED) {
        LOGD("%s MI_VOC_Init is failed(%d).", __FUNCTION__, eErrCode);
        dlclose(pLibraryHandle);
        return MI_FAILURE;
    }
    return MI_SUCCESS;
}

int MicConfig::DeInitMic() {
    MI_RESULT eErrCode = MI_OK;

    eErrCode = g_pFunc_voc_deinit();
    if (eErrCode != MI_OK) {
        LOGD("%s MI_VOC_DeInit is failed(%d).", __FUNCTION__, eErrCode);
        return MI_FAILURE;
    }
    dlclose(pLibraryHandle);
    LOGD("haier_vol_control_deinit success !");
    return MI_SUCCESS;
}

int MicConfig::OpenMic(int channelNum, int sampleRate) {
    MI_VOC_OpenParams_t stOpenParams;
    MI_RESULT eErrCode = MI_OK;

    memset(&stOpenParams, 0, sizeof(MI_VOC_OpenParams_t));

    stOpenParams.bDoPreprocess = false;
    stOpenParams.stPcmConfigs.u32SampleRate = (MI_U32) sampleRate;
    stOpenParams.stPcmConfigs.u8OutputChannelNumber = (MI_U32) channelNum;
    stOpenParams.stPcmConfigs.ePcmFormat = E_MI_VOC_PCM_FORMAT_S16_LE;

    LOGD("    %s, bDoPreprocess:            %u", __FUNCTION__, stOpenParams.bDoPreprocess);
    LOGD("    %s, u32SampleRate:            %u", __FUNCTION__,
         stOpenParams.stPcmConfigs.u32SampleRate);
    LOGD("    %s, u8OutputChannelNumber:    %u", __FUNCTION__,
         stOpenParams.stPcmConfigs.u8OutputChannelNumber);
    LOGD("    %s, ePcmFormat:               %u", __FUNCTION__,
         stOpenParams.stPcmConfigs.ePcmFormat);

    eErrCode = g_pFunc_voc_open(&stOpenParams, &mHandle);
    if (eErrCode != MI_OK) {
        if (eErrCode == MI_ERR_RESOURCES) {
            LOGI("MI_VOC handle[%d] already open and not close yet", mHandle);
        } else {
            LOGD("%s MI_VOC_Open is failed(%d).", __FUNCTION__, eErrCode);
        }
    } else {
        LOGD("Haier_vol_control_open Success !\n");
        LOGD("MI_VOC handle [%d]", mHandle);
    }
    return eErrCode;
}

int MicConfig::CloseMic() {
    if (g_pFunc_voc_close((MI_HANDLE) mHandle) != MI_OK) {
        LOGD("MI_VOC_Close is failed(%s).", __FUNCTION__);
    }
    LOGD("haier_vol_control_close success\n");
    return MI_SUCCESS;
}

int MicConfig::getHandle(MI_HANDLE *phVoc) {
    return 0;
}

int MicConfig::readMic(void *data, unsigned int frame_count) {
    int ret;
    MI_RESULT eErrCode = MI_OK;
    MI_VOC_ReadParams_t stReadParams;
    MI_VOC_ReadOutputParams_t stReadOutputParams;

    if (mHandle == 0) {
        LOGE("[%s]:open failed from read function.", __FUNCTION__);
        return MI_FAILURE;
    }

    memset(&stReadParams, 0, sizeof(MI_VOC_ReadParams_t));
    memset(&stReadOutputParams, 0, sizeof(MI_VOC_ReadOutputParams_t));
    stReadParams.u32FrameSize = (MI_U32) frame_count;
    stReadOutputParams.pPcmBuf = (void *) data;

    eErrCode = g_pFunc_voc_read(mHandle, &stReadParams, &stReadOutputParams);
    if (eErrCode == MI_OK) {
        ret = stReadOutputParams.u32PcmDataSize;
    } else {
        LOGE("MI_VOC_Read read fail, eErrCode: %d", eErrCode);
        ret = -eErrCode;
    }
    return ret;
}
